#include <iostream>
#include "unistd.h"
#include <sys/types.h>
#include<sys/wait.h>
#include <pwd.h>
#include <readline/readline.h>
#include "Buildin_Command.h"
#define TRUE 1

#define MAX 10
#define MAXLINE 4096
#define MAXARG 20





void type_prompt(void);

int read_command(char* &command,char **&parameters,char *prompt,read_info* info);


char* buffer;
const int len=50;
char hostName[len];
char* path;
char* name;
char* command;
char** parameters;
char* buffer2;
char* command2;
char** parameters2;
read_info * info;



int main() {
    //初始化内建函数列表
    Init();

    int pi[2];
    int status=0;
    char* prompt;
    char* out;
    info=new read_info;
    pid_t pid,pid2;
    prompt=NULL;
    //command=(char*)malloc(sizeof(char)*MAX);
    parameters = (char **)malloc(sizeof(char *)*(MAXARG+2));
    parameters2 = (char **)malloc(sizeof(char *)*(MAXARG+2));
    buffer = (char *)malloc(sizeof(char) * MAXLINE);
    while(TRUE) {
        type_prompt();/* display prompt on the screen */
        read_command(command,parameters,prompt,info); /* read input from terminal */




        if(info->IsBuildin&&isFork(info->index)==NO_FORK){
            run(info->index,parameters,out);
            continue;
        }

        if(info->IsPipe){
            pipe(pi);
        }

        if((pid=fork())!=0) { /* fork off child process */
            /* Parent code */
            waitpid(-1,&status,0);  /* wait for child to exit */
            if(info->IsPipe){
                //第二个子进程
                if((pid2=fork())==0){

#ifdef DEBUG                     //第三个子进程

                    if(fork()==0){
                        sleep(1);
                        int com;
                        while(com=getchar()){
                            if(com=='q'){
                                kill(getppid(),SIGTERM);
                                return 0;
                            } else{
                                sleep(0.1);
                            }
                        }
                        return 0;

                    }
#endif

                    close(pi[1]);
                    dup2(pi[0],STDIN_FILENO);
//                    DoCommand(info,command2,parameters2,out);
//                    break;
                    if(info->Redirect2!=NULL){
                        Redirection(info,info->Redirect2);
                    }
                    if(info->IsBuildin2){
                        run(info->index2,parameters2,out);
                        break;
                    } else{
                        if(info->IsPath2== false){
                            if(execvp(command2,parameters2)==-1){
                                printf("%s is not exist\n",&command2);
                                //repipe();
                                close(pi[0]);
                                break;
                            }
                        }/* execute command */
                        else{
                            if(execv(info->Path2,parameters2)==-1){
                                printf("%s is not exist\n",&command2);
                                close(pi[0]);
                                break;
                            }
                        }
                    }

                } else{
#ifdef DEBUGs                     //第三个子进程
                    if(fork()==0){
                        int com;
                        while(com=getchar()){
                            if(com=='q'){
                                kill(pid2,SIGTERM);
                                return 0;
                            }
                        }
                        return 0;

                    }
#endif
                }

            }
            //kill(pid2,SIGTERM);
            waitpid(-1,&status,0);  /* wait for child to exit */

            } else {
                if(info->IsPipe){
                    close(pi[0]);
                    dup2(pi[1],STDOUT_FILENO);
                }
                if(info->Redirect!=NULL){
                    Redirection(info,info->Redirect);
                }
                if(info->IsBuildin){
                    run(info->index,parameters,out);
                    break;
                } else{
                        if(info->IsPath== false){
                            execvp(command,parameters);
                        }/* execute command */
                        else{
                            execv(info->Path,parameters);
                        }
                }
            }
    }
}


void type_prompt(void){
    char end;
    passwd * pd= getpwuid(getuid());
    //getlogin_r(name,len);
    gethostname(hostName,len);
    path=get_current_dir_name();
    if(strstr(path,pd->pw_dir)==path){
        path=path+strlen(pd->pw_dir)-1;
        path[0]='~';
    }
    if(geteuid()==0){
        end='#';
    } else{
        end='$';
    }
    printf("[MYSHELL]%s@%s:%s%c ",pd->pw_name,&hostName,path,end);
}

int read_command(char* &command,char **&parameters,char * prompt,read_info* info){

    free(buffer);
    buffer = readline(prompt);
    if(feof(stdin)) {
        printf("\n");
        exit(0);
    }




    if(strlen(buffer)<=0) return -1;

    if(strrchr(buffer,'|')!=0){
        info->IsPipe=true;
        buffer2=strrchr(buffer,'|');
        *buffer2='\0';
        buffer2=buffer2+1;
    } else{
        info->IsPipe= false;
    }

    // 1:>> 2:> 3:<< 4:<
    if((info->Redirect=strstr(buffer,">>"))!=NULL){
        *(info->Redirect)='\0';
        info->Redirect=info->Redirect+2;
        info->IsRedirect=1;
    } else{
            if((info->Redirect=strrchr(buffer,'>'))!=NULL){
                *(info->Redirect)='\0';
                info->Redirect=info->Redirect+1;
                info->IsRedirect=2;
            } else{
                if((info->Redirect=strrchr(buffer,'<'))!=NULL){
                    *(info->Redirect)='\0';
                    info->Redirect=info->Redirect+1;
                    info->IsRedirect=4;
                } else{
                    info->IsRedirect=0;
                }
            }
    }
    if(buffer[0]=='/'||((buffer[0]=='.')&&(buffer[1]=='/'))){
        info->IsBuildin= false;
        info->IsPath= true;
        if((info->Path=strtok(buffer," "))==NULL){
            info->Path=buffer;
        } else{
            for(int i=1;i<MAXARG;i++){
                if((parameters[i]=strtok(NULL," "))== nullptr){
                    parameters[i]=NULL;
                    break;
                }
            }
        }
        command=strrchr(info->Path,'/')+1;
    }
    else{
        info->IsPath= false;
        if((command=strtok(buffer," "))== NULL) command=buffer;
        else{
            for(int i=1;i<MAXARG;i++){
                if((parameters[i]=strtok(NULL," "))== nullptr){
                    parameters[i]=NULL;
                    break;
                }
                else{
                    //printf("%s\n",parameters[i]);
                }
            }

        }
        if((info->index=GetIndex(command))!=-1){
            info->IsBuildin= true;
        } else{
            info->IsBuildin= false;
        }

    }
    parameters[0]=command;


    if(info->IsPipe){
        if((info->Redirect2=strstr(buffer2,">>"))!=NULL){
            *(info->Redirect2)='\0';
            info->Redirect2=info->Redirect2+2;
            info->IsRedirect2=1;
        } else{
            if((info->Redirect2=strrchr(buffer2,'>'))!=NULL){
                *(info->Redirect2)='\0';
                info->Redirect2=info->Redirect2+1;
                info->IsRedirect2=2;
            } else{
                if((info->Redirect2=strrchr(buffer2,'<'))!=NULL){
                    *(info->Redirect2)='\0';
                    info->Redirect2=info->Redirect2+1;
                    info->IsRedirect2=4;
                } else{
                    info->IsRedirect2=0;
                }
            }
        }
        if(buffer2[0]=='/'||((buffer2[0]=='.')&&(buffer2[1]=='/'))){
            info->IsBuildin2= false;
            info->IsPath2= true;
            if((info->Path2=strtok(buffer2," "))==NULL){
                info->Path2=buffer2;
            } else{
                for(int i=1;i<MAXARG;i++){
                    if((parameters2[i]=strtok(NULL," "))== nullptr){
                        parameters2[i]=NULL;
                        break;
                    }
                }
            }
            command2=strrchr(info->Path2,'/')+1;
        }
        else{
            info->IsPath2= false;
            if((command2=strtok(buffer2," "))== NULL) command2=buffer2;
            else{
                for(int i=1;i<MAXARG;i++){
                    if((parameters2[i]=strtok(NULL," "))== nullptr){
                        parameters2[i]=NULL;
                        break;
                    }
                    else{
                        //printf("%s\n",parameters2[i]);
                    }
                }

            }
            if((info->index2=GetIndex(command2))!=-1){
                info->IsBuildin2= true;
            } else{
                info->IsBuildin2= false;
            }

        }
        parameters2[0]=command2;
    }

    //if have pipe , anay buffer2

}